home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / cvs-1_3.lha / cvs-1.3 / contrib / log_accum.pl < prev    next >
Perl Script  |  1992-04-10  |  9KB  |  332 lines

  1. #!/usr/local/bin/perl -w
  2. #
  3. # Perl filter to handle the log messages from the checkin of files in
  4. # a directory.  This script will group the lists of files by log
  5. # message, and mail a single consolidated log message at the end of
  6. # the commit.
  7. #
  8. # This file assumes a pre-commit checking program that leaves the
  9. # names of the first and last commit directories in a temporary file.
  10. #
  11. # Contributed by David Hampton <hampton@cisco.com>
  12. #
  13.  
  14. ############################################################
  15. #
  16. # Configurable options
  17. #
  18. ############################################################
  19. #
  20. # Do cisco Systems, Inc. specific nonsense.
  21. #
  22. $cisco_systems = 1;
  23.  
  24. #
  25. # Recipient of all mail messages
  26. #
  27. $mailto = "sw-notification@cisco.com";
  28.  
  29. ############################################################
  30. #
  31. # Constants
  32. #
  33. ############################################################
  34. $STATE_NONE    = 0;
  35. $STATE_CHANGED = 1;
  36. $STATE_ADDED   = 2;
  37. $STATE_REMOVED = 3;
  38. $STATE_LOG     = 4;
  39.  
  40. $LAST_FILE     = "/tmp/#cvs.lastdir";
  41. $CHANGED_FILE  = "/tmp/#cvs.files.changed";
  42. $ADDED_FILE    = "/tmp/#cvs.files.added";
  43. $REMOVED_FILE  = "/tmp/#cvs.files.removed";
  44. $LOG_FILE      = "/tmp/#cvs.files.log";
  45. $FILE_PREFIX   = "#cvs.files";
  46.  
  47. $VERSION_FILE  = "version";
  48. $TRUNKREV_FILE = "TrunkRev";
  49. $CHANGES_FILE  = "Changes";
  50. $CHANGES_TEMP  = "Changes.tmp";
  51.  
  52. ############################################################
  53. #
  54. # Subroutines
  55. #
  56. ############################################################
  57.  
  58. sub format_names {
  59.     local($dir, @files) = @_;
  60.     local(@lines);
  61.     $lines[0] = sprintf(" %-08s", $dir);
  62.     foreach $file (@files) {
  63.     if (length($lines[$#lines]) + length($file) > 60) {
  64.         $lines[++$#lines] = sprintf(" %8s", " ");
  65.     }
  66.     $lines[$#lines] .= " ".$file;
  67.     }
  68.     @lines;
  69. }
  70.  
  71. sub cleanup_tmpfiles {
  72.     local($all) = @_;
  73.     local($wd, @files);
  74.  
  75.     $wd = `pwd`;
  76.     chdir("/tmp");
  77.     opendir(DIR, ".");
  78.     if ($all == 1) {
  79.     push(@files, grep(/$id$/, readdir(DIR)));
  80.     } else {
  81.     push(@files, grep(/^$FILE_PREFIX.*$id$/, readdir(DIR)));
  82.     }
  83.     closedir(DIR);
  84.     foreach (@files) {
  85.     unlink $_;
  86.     }
  87.     chdir($wd);
  88. }
  89.  
  90. sub write_logfile {
  91.     local($filename, @lines) = @_;
  92.     open(FILE, ">$filename") || die ("Cannot open log file $filename.\n");
  93.     print(FILE join("\n", @lines), "\n");
  94.     close(FILE);
  95. }
  96.  
  97. sub append_to_file {
  98.     local($filename, $dir, @files) = @_;
  99.     if (@files) {
  100.     local(@lines) = &format_names($dir, @files);
  101.     open(FILE, ">>$filename") || die ("Cannot open file $filename.\n");
  102.     print(FILE join("\n", @lines), "\n");
  103.     close(FILE);
  104.     }
  105. }
  106.  
  107. sub write_line {
  108.     local($filename, $line) = @_;
  109.     open(FILE, ">$filename") || die("Cannot open file $filename.\n");
  110.     print(FILE $line, "\n");
  111.     close(FILE);
  112. }
  113.  
  114. sub read_line {
  115.     local($line);
  116.     local($filename) = @_;
  117.     open(FILE, "<$filename") || die("Cannot open file $filename.\n");
  118.     $line = <FILE>;
  119.     close(FILE);
  120.     chop($line);
  121.     $line;
  122. }
  123.  
  124. sub read_file {
  125.     local(@text);
  126.     local($filename, $leader) = @_;
  127.     open(FILE, "<$filename") || return ();
  128.     while (<FILE>) {
  129.     chop;
  130.     push(@text, sprintf("  %-10s  %s", $leader, $_));
  131.     $leader = "";
  132.     }
  133.     close(FILE);
  134.     @text;
  135. }
  136.  
  137. sub read_logfile {
  138.     local(@text);
  139.     local($filename, $leader) = @_;
  140.     open(FILE, "<$filename") || die ("Cannot open log file $filename.\n");
  141.     while (<FILE>) {
  142.     chop;
  143.     push(@text, $leader.$_);
  144.     }
  145.     close(FILE);
  146.     @text;
  147. }
  148.  
  149. sub bump_version {
  150.     local($trunkrev, $editnum, $version);
  151.  
  152.     $trunkrev = &read_line("$ENV{'CVSROOT'}/$repository/$TRUNKREV_FILE");
  153.     $editnum  = &read_line("$ENV{'CVSROOT'}/$repository/$VERSION_FILE");
  154.     &write_line("$ENV{'CVSROOT'}/$repository/$VERSION_FILE", $editnum+1);
  155.     $version = $trunkrev . "(" . $editnum . ")";
  156. }
  157.  
  158. sub build_header {
  159.     local($version) = @_;
  160.     local($header);
  161.     local($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  162.     $header = sprintf("%-8s  %s  %02d/%02d/%02d %02d:%02d:%02d",
  163.                $login, $version, $year%100, $mon+1, $mday,
  164.                $hour, $min, $sec);
  165. }
  166.  
  167. sub do_changes_file {
  168.     local($changes, $tmpchanges);
  169.     local(@text) = @_;
  170.  
  171.     $changes = "$ENV{'CVSROOT'}/$repository/$CHANGES_FILE";
  172.     $tmpchanges = "$ENV{'CVSROOT'}/$repository/$CHANGES_TEMP";
  173.     if (rename($changes, $tmpchanges) != 1) {
  174.     die("Cannot rename $changes to $tmpchanges.\n");
  175.     }
  176.     open(CHANGES, ">$changes") || die("Cannot open $changes.\n");
  177.     open(TMPCHANGES, "<$tmpchanges") || die("Cannot open $tmpchanges.\n");
  178.     print(CHANGES join("\n", @text), "\n\n");
  179.     print(CHANGES <TMPCHANGES>);
  180.     close(CHANGES);
  181.     close(TMPCHANGES);
  182.     unlink($tmpchanges);
  183. }
  184.  
  185. sub mail_notification {
  186.     local($name, @text) = @_;
  187.     open(MAIL, "| mail -s \"Source Repository Modification\" $name");
  188.     print(MAIL join("\n", @text));
  189.     close(MAIL);
  190. }
  191.  
  192. #############################################################
  193. #
  194. # Main Body
  195. #
  196. ############################################################
  197.  
  198. #
  199. # Initialize basic variables
  200. #
  201. $id = getpgrp();
  202. $state = $STATE_NONE;
  203. $login = getlogin || (getpwuid($<))[0] || die("Unknown user $<.\n");
  204. @files = split(' ', $ARGV[0]);
  205. @path = split('/', $files[0]);
  206. $repository = @path[0];
  207. if ($#path == 0) {
  208.     $dir = ".";
  209. } else {
  210.     $dir = join('/', @path[1..$#path]);
  211. }
  212. #print("ARGV  - ", join(":", @ARGV), "\n");
  213. #print("files - ", join(":", @files), "\n");
  214. #print("path  - ", join(":", @path), "\n");
  215. #print("dir   - ", $dir, "\n");
  216. #print("id    - ", $id, "\n");
  217.  
  218. #
  219. # Check for a new directory first.  This will always appear as a
  220. # single item in the argument list, and an empty log message.
  221. #
  222. if ($ARGV[0] =~ /New directory/) {
  223.     $version = &bump_version if ($cisco_systems != 0);
  224.     $header = &build_header($version);
  225.     @text = ();
  226.     push(@text, $header);
  227.     push(@text, "");
  228.     push(@text, "  ".$ARGV[0]);
  229.     &do_changes_file(@text) if ($cisco_systems != 0);
  230.     &mail_notification($mailto, @text);
  231.     exit 0;
  232. }
  233.  
  234. #
  235. # Iterate over the body of the message collecting information.
  236. #
  237. while (<STDIN>) {
  238.     chop;            # Drop the newline
  239.     if (/^Modified Files/) { $state = $STATE_CHANGED; next; }
  240.     if (/^Added Files/)    { $state = $STATE_ADDED;   next; }
  241.     if (/^Removed Files/)  { $state = $STATE_REMOVED; next; }
  242.     if (/^Log Message/)    { $state = $STATE_LOG;     next; }
  243.     s/^[ \t\n]+//;        # delete leading space
  244.     s/[ \t\n]+$//;        # delete trailing space
  245.     
  246.     push (@changed_files, split) if ($state == $STATE_CHANGED);
  247.     push (@added_files,   split) if ($state == $STATE_ADDED);
  248.     push (@removed_files, split) if ($state == $STATE_REMOVED);
  249.     push (@log_lines,     $_)    if ($state == $STATE_LOG);
  250. }
  251.  
  252. #
  253. # Strip leading and trailing blank lines from the log message.  Also
  254. # compress multiple blank lines in the body of the message down to a
  255. # single blank line.
  256. #
  257. while ($#log_lines > -1) {
  258.     last if ($log_lines[0] ne "");
  259.     shift(@log_lines);
  260. }
  261. while ($#log_lines > -1) {
  262.     last if ($log_lines[$#log_lines] ne "");
  263.     pop(@log_lines);
  264. }
  265. for ($i = $#log_lines; $i > 0; $i--) {
  266.     if (($log_lines[$i - 1] eq "") && ($log_lines[$i] eq "")) {
  267.     splice(@log_lines, $i, 1);
  268.     }
  269. }
  270.  
  271. #
  272. # Find the log file that matches this log message
  273. #
  274. for ($i = 0; ; $i++) {
  275.     last if (! -e "$LOG_FILE.$i.$id");
  276.     @text = &read_logfile("$LOG_FILE.$i.$id", "");
  277.     last if ($#text == -1);
  278.     last if (join(" ", @log_lines) eq join(" ", @text));
  279. }
  280.  
  281. #
  282. # Spit out the information gathered in this pass.
  283. #
  284. &write_logfile("$LOG_FILE.$i.$id", @log_lines);
  285. &append_to_file("$ADDED_FILE.$i.$id",   $dir, @added_files);
  286. &append_to_file("$CHANGED_FILE.$i.$id", $dir, @changed_files);
  287. &append_to_file("$REMOVED_FILE.$i.$id", $dir, @removed_files);
  288.  
  289. #
  290. # Check whether this is the last directory.  If not, quit.
  291. #
  292. $_ = &read_line("$LAST_FILE.$id");
  293. exit 0 if (! grep(/$files[0]$/, $_));
  294.  
  295. #
  296. # This is it.  The commits are all finished.  Lump everything together
  297. # into a single message, fire a copy off to the mailing list, and drop
  298. # it on the end of the Changes file.
  299. #
  300. # Get the full version number
  301. #
  302. $version = &bump_version if ($cisco_systems != 0);
  303. $header = &build_header($version);
  304.  
  305. #
  306. # Produce the final compilation of the log messages
  307. #
  308. @text = ();
  309. push(@text, $header);
  310. push(@text, "");
  311. for ($i = 0; ; $i++) {
  312.     last if (! -e "$LOG_FILE.$i.$id");
  313.     push(@text, &read_file("$CHANGED_FILE.$i.$id", "Modified:"));
  314.     push(@text, &read_file("$ADDED_FILE.$i.$id", "Added:"));
  315.     push(@text, &read_file("$REMOVED_FILE.$i.$id", "Removed:"));
  316.     push(@text, "  Log:");
  317.     push(@text, &read_logfile("$LOG_FILE.$i.$id", "  "));
  318.     push(@text, "");
  319. }
  320. if ($cisco_systems != 0) {
  321.     @ddts = grep(/^CSCdi/, split(' ', join(" ", @text)));
  322.     $text[0] .= "  " . join(" ", @ddts);
  323. }
  324. #
  325. # Put the log message at the beginning of the Changes file and mail
  326. # out the notification.
  327. #
  328. &do_changes_file(@text) if ($cisco_systems != 0);
  329. &mail_notification($mailto, @text);
  330. &cleanup_tmpfiles(1);
  331. exit 0;
  332.